package cn.edu.lsu.integratedsurvey.controller;

import cn.edu.lsu.integratedsurvey.bean.dto.LoginDto;
import cn.edu.lsu.integratedsurvey.bean.dto.UserChangeDto;
import cn.edu.lsu.integratedsurvey.bean.dto.UserRegisterDto;
import cn.edu.lsu.integratedsurvey.bean.vo.HistoryInfoVo;
import cn.edu.lsu.integratedsurvey.bean.vo.LoginVo;
import cn.edu.lsu.integratedsurvey.bean.vo.UserInfoVo;
import cn.edu.lsu.integratedsurvey.service.LoginRecordsService;
import cn.edu.lsu.integratedsurvey.service.StudentService;
import cn.edu.lsu.integratedsurvey.service.UserService;
import cn.edu.lsu.integratedsurvey.tool.JwtUtil;
import cn.edu.lsu.integratedsurvey.tool.R;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.jsonwebtoken.Claims;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;


/**
 * @author Jasmine-drs
 * @date 2024/5/1 11:13
 */

@Slf4j
@Api("管理员模块")
@RestController
@RequestMapping("/users")
public class UserController {
	final UserService userService;// user的业务逻辑对象
	final StudentService studentService;//  student的业务逻辑对象
	final JwtUtil jwtUtil;//    jwt鉴权的工具类，判断是否是管理员（admin）或者root
	private final LoginRecordsService loginRecordsService;

	public UserController(UserService userService, StudentService studentService, JwtUtil jwtUtil, LoginRecordsService loginRecordsService) {
		this.userService = userService;
		this.studentService = studentService;
		this.jwtUtil = jwtUtil;
		this.loginRecordsService = loginRecordsService;
	}

	/**
	 * 管理员登录，输入账号密码，然后返回登录状态
	 * 第一次登录需要引导修改密码，此时客户端删除第一次登录的jwt，并且调用登出接口使服务器删除第一次的jwt
	 * 然后改完密码重新登录，再次调用登录接口获取jwt
	 *
	 * @param userLogin 用户登录信息，包含账号密码
	 * @return 用户登录信息包含jwt
	 */
	@PostMapping("/login")
	@ApiOperation("管理员登录")
	public R<LoginVo> login(@RequestBody LoginDto userLogin) {
		if (log.isDebugEnabled()) {
			log.debug("login=>用户名：{}，密码：{}", userLogin.getAccount(), userLogin.getPassword());
		}
//		不为空校验
		if (userLogin.getAccount().isBlank() || userLogin.getPassword().isBlank()) {
			return R.err("账号或密码不能为空");
		}
//		调用登录方法，返回jwt
		LoginVo token = userService.login(userLogin);
		return R.success(token);
	}

	/**
	 * 退出登录
	 *
	 * @param authHeader jwt
	 * @return 登出结果
	 */
	@GetMapping("/logout")
	@ApiOperation("管理员登出")
	public R<String> logout(@RequestHeader("Authorization") String authHeader) {
		if (log.isDebugEnabled()) {
			log.debug("logout=>authHeader:{}", authHeader);
		}
//		提取头部的jwt信息
		Map<String, Object> token = jwtUtil.parseToken(authHeader);
//		调用登出方法,如果需要实现，则需要存储jwt信息，然后进行校验，登出进行删除
		loginRecordsService.logout(authHeader);
		return R.success((String) token.get("status"));
	}

	/**
	 * 超级管理员注册普通管理员，需要有root权限
	 *
	 * @param userRegisterDto 需注册的用户信息
	 * @return 注册结果
	 */
	@PostMapping("/root/register")
	@ApiOperation("管理员注册")
	public R<String> register(@RequestBody UserRegisterDto userRegisterDto, @RequestHeader("Authorization") String authHeader) {
		if (log.isDebugEnabled()) {
			log.debug("userRegisterDto:{}", userRegisterDto);
			log.debug("authHeader:{}", authHeader);
		}
//		提取头部的jwt信息，进行鉴权
		if (jwtUtil.isRoot(authHeader)) {
			Map<String, Object> token = jwtUtil.parseToken(authHeader);
			Claims claims = (Claims) token.get("claims");
			Integer operatorId = (Integer) claims.get("id");
//		调用注册方法
			boolean register = userService.register(userRegisterDto, operatorId);
			if (register) {
				return R.success("注册成功");
			}else {
				return R.err("注册失败");
			}
		}
		throw new RuntimeException("权限不足");
	}

	/**
	 * 根据管理员id获取管理员操作记录，需要有root权限
	 *
	 * @param id         普通管理员的id
	 * @param authHeader jwt
	 * @param pageNumber 当前页数
	 * @param pageSize   当前页大小
	 * @return 操作记录列表
	 */
	@GetMapping("/root/{id}")
	@ApiOperation("获取管理员操作记录")
	public R<Page<HistoryInfoVo>> getUser(@PathVariable Integer id,
	                                      @RequestHeader("Authorization") String authHeader,
	                                      @RequestParam(defaultValue = "1") Integer pageNumber,
	                                      @RequestParam(defaultValue = "10") Integer pageSize) {
		if (log.isDebugEnabled()) {
			log.debug("id:{}", id);
			log.debug("authHeader:{}", authHeader);
		}
//		提取头部的jwt信息，进行鉴权
		if (jwtUtil.isRoot(authHeader)){
//		调用获取管理员信息方法
			return R.success(userService.getHistoryInfoById(id, pageNumber, pageSize));
		}
		throw new RuntimeException("权限不足");
	}

	/**
	 * 获取普通管理员列表，需要有root权限
	 *
	 * @param authHeader jwt
	 * @return 管理员信息列表
	 */
	@GetMapping("/root/all")
	@ApiOperation("获取所有管理员信息")
	public R<List<UserInfoVo>> getAllUser(@RequestHeader("Authorization") String authHeader) {
		if (log.isDebugEnabled()) {
			log.debug("authHeader:{}", authHeader);
		}
//		提取头部的jwt信息，进行鉴权
		if (jwtUtil.isRoot(authHeader)){
//		调用获取所有管理员信息方法
			return R.success(userService.getAllUser());
		}
		throw new RuntimeException("权限不足");
	}

	/**
	 * 根据账号或姓名搜索管理员，需要有root权限
	 * 搜索栏中的内容不需要处理，直接传给keyword即可
	 *
	 * @param keyword    关键字，账号或姓名
	 * @param authHeader jwt
	 * @return 管理员信息列表
	 */
	@GetMapping("/root/search")
	@ApiOperation("根据账号或姓名搜索管理员")
	public R<List<UserInfoVo>> searchUser(String keyword, @RequestHeader("Authorization") String authHeader) {
		if (log.isDebugEnabled()) {
			log.debug("keyword:{}", keyword);
			log.debug("authHeader:{}", authHeader);
		}
//		提取头部的jwt信息，进行鉴权
		if (jwtUtil.isRoot(authHeader)){
//		调用搜索管理员方法
			return R.success(userService.searchUser(keyword));
		}
		throw new RuntimeException("权限不足");
	}


	/**
	 * 删除管理员，需要有root权限
	 * 此接口是逻辑删除
	 *
	 * @param id         管理员id
	 * @param authHeader jwt
	 * @return 删除结果
	 */
	@DeleteMapping("/root/{id}")
	@ApiOperation("删除管理员")
	public R<String> deleteUser(@PathVariable Integer id, @RequestHeader("Authorization") String authHeader) {
		if (log.isDebugEnabled()) {
			log.debug("id:{}", id);
			log.debug("authHeader:{}", authHeader);
		}
//		提取头部的jwt信息，进行鉴权
		if (jwtUtil.isRoot(authHeader)){
//		调用删除管理员方法
			boolean b = userService.removeById(id);
			if (!b) {
				return R.err("删除失败");
			}
			return R.success("删除成功");
		}
		throw new RuntimeException("权限不足");
	}

	/**
	 * 修改密码之前先调这个接口，确认旧密码是否正确，管理员权限
	 * 鼠标焦点离开旧密码框时调用
	 *
	 * @param userChangeDto 用户信息，包含账号和旧密码
	 * @param authHeader    jwt
	 * @return 是否确认成功
	 */
	@PostMapping("/change/confirm")
	@ApiOperation("确认旧密码")
	public R<String> confirmPassword(@RequestBody UserChangeDto userChangeDto, @RequestHeader("Authorization") String authHeader) {
		if (log.isDebugEnabled()) {
			log.debug("userChangeDto:{}", userChangeDto);
			log.debug("authHeader:{}", authHeader);
		}
//		提取头部的jwt信息，进行鉴权
		if (jwtUtil.isAdmin(authHeader)){
//		调用确认密码方法
			if (userService.confirmPassword(userChangeDto)) {
				return R.success("密码正确");
			}
			return R.err("密码错误");
		}
		throw new RuntimeException("权限不足");
	}

	/**
	 * 修改密码,需要有管理员权限
	 *
	 * @param userChangeDto 用户信息，包含账号、旧密码和新密码
	 * @param authHeader    jwt
	 * @return 是否修改成功
	 */
	@PutMapping("/change")
	@ApiOperation("修改密码")
	public R<String> changePassword(@RequestBody UserChangeDto userChangeDto, @RequestHeader("Authorization") String authHeader) {
		if (log.isDebugEnabled()) {
			log.debug("user:{}", userChangeDto);
			log.debug("authHeader:{}", authHeader);
		}
//		提取头部的jwt信息，进行鉴权
		if (jwtUtil.isAdmin(authHeader)){
//		调用修改密码方法
			if (userService.changePassword(userChangeDto)) {
				return R.success("修改成功");
			}
			return R.err("修改失败");
		}
		throw new RuntimeException("权限不足");
	}

	/**
	 * 重置密码
	 * 适用于忘记自己的密码，重置为初始密码，也就是跟账号一致
	 * 注意重置完之后需要跳转到登录，并且引导修改密码，与第一次登录流程一致
	 *
	 * @param account 需要重置的账号
	 * @return 重置结果
	 */
	@PutMapping("/reset")
	@ApiOperation("重置密码")
	public R<String> resetPassword(@RequestParam String account, @RequestHeader("Authorization") String authHeader) {
		if (log.isDebugEnabled()) {
			log.debug("account:{}", account);
			log.debug("authHeader:{}", authHeader);
		}
//		提取头部的jwt信息，进行鉴权
		if (jwtUtil.isRoot(authHeader)){
//		调用重置密码方法
			if (userService.resetPassword(account)) {
				return R.success("重置成功");
			}
			return R.err("重置失败");
		}
		throw new RuntimeException("权限不足");
	}
}
